<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Article</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
<link rel="stylesheet" href= "../assets/markdownLayout/git_md.css">
<link rel="stylesheet" href= "../assets/theme/theme_fresh.css">
<link rel="stylesheet" href= "../assets/hightlightStyle/atom-one-light.css">

<style>
    .markdown-body{
        box-sizing: border-box;
        min-width: 200px;
        max-width: 980px;
        margin: 0 auto;
        padding: 45px;
    }

    @media (max-width: 767px) {
        .markdown-body {
            padding: 15px;
        }
    }
</style>


</head>
<body>
    
    <!--header-->
    <div class="header">
    <header>
        <div class="logo"><a href="../index.html"><span>hh2o4</span></a></div>
        <nav>
            
                <li> <a href="#">articles</a> </li>
                <li> <a href="../contact.html">contact</a> </li>
                <li> <a href="#">pictures</a> </li>
            
        </nav>
    </header>
</div>

    <!--content-->
    <div class="content">
        <h1>前端各知识点学习笔记</h1>
        <div class="info"><span class="date">发表时间: 2017-08-01</span></div>
        <article class="markdown-body">
            <p>这篇笔记持续更新，用于记录学习过程中和准备面试过程中遇到的问题，以及尝试去得到的解答。</p>
<h1 id="css">CSS</h1>
<h2 id="-">面经</h2>
<h2 id="-">学习</h2>
<h3 id="q1-">Q1. 浮动和浮动清除</h3>
<h3 id="q2-background-position-background-origin-">Q2. background-position与background-origin的关系</h3>
<p>background-origin规定了background-position相对于谁定位。
background-origin的默认值是padding-box.</p>
<h3 id="q3-linear-gradient-radial-gradient-">Q3. linear-gradient和radial-gradient函数</h3>
<h3 id="q4-border-border-radius">Q4. border与border-radius</h3>
<p>border:none; border-radius: somevalue px;会把背景设为圆角，而不显示边框。</p>
<h3 id="q5-transimition-animation-step-">Q5. transimition和animation中的step()函数的理解。</h3>
<p><a href="http://www.cnblogs.com/aaronjs/p/4642015.html">深入理解CSS3 Animation 帧动画</a></p>
<h3 id="q6-calc-">Q6. 如何用calc()方法灵活这顶元素的宽度与高度？</h3>
<h3 id="q7-">Q7. 自己实现的一个栅格系统</h3>
<p><a href="https://git.oschina.net/hh2o4/baidu_ife/blob/master/Task1_8/style.css">https://git.oschina.net/hh2o4/baidu_ife/blob/master/Task1_8/style.css</a></p>
<h3 id="q8-css-">Q8. css怎么实现硬件加速</h3>
<p>为动画DOM元素添加CSS3样式-webkit-transform:transition3d(0,0,0)或-webkit-transform:translateZ(0);，这两个属性都会开启GPU硬件加速模式，<strong>从而让浏览器在渲染动画时从CPU转向GPU</strong>，其实说白了这是一个小伎俩，也可以算是一个Hack，-webkit-transform:transition3d和-webkit-transform:translateZ其实是为了渲染3D样式，但我们设置值为0后，并没有真正使用3D效果，但浏览器却因此开启了GPU硬件加速模式。</p>
<p>　　这种GPU硬件加速在当今PC机及移动设备上都已普及，在移动端的性能提升是相当显著地，所以建议大家在做动画时可以尝试一下开启GPU硬件加速。</p>
<h1 id="js">JS</h1>
<h2 id="-">面经</h2>
<h3 id="q1-jsonp-">Q1. 手写jsonp的实现</h3>
<p>JSONP(JSON with Padding)</p>
<ul>
<li>原理：服务器端返回一个函数调用表达式，在script标签中被立即执行。函数的接收参数是一个JSON对象，函数名是由script标签的src中url的查询字符串来指定的。后端识别特别的查询字符串（比如callback、jsonp...字段，没有标准）得知函数名。</li>
<li>注意：每次发起JSONP后，应删除定义的callback函数（因为一般callback函数要求不重名，于是每一次发起JSONP都会定义一个callback函数，不删除的话，可能导致全局产生过多的函数），并删除为了JSONP而动态生成的script标签。</li>
<li>手写JSONP：</li>
</ul>
<pre><code class="lang-js"><span class="hljs-comment">//全局定义域，假设后端已协商好表示回调函数的key为callback</span>

<span class="hljs-comment">//定义回调函数</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">json</span>) </span>{
    <span class="hljs-comment">//do something.</span>
}

<span class="hljs-comment">//创建url</span>
<span class="hljs-keyword">var</span> query = <span class="hljs-string">"callback=handler"</span>;

<span class="hljs-comment">//创建script元素</span>
<span class="hljs-keyword">var</span> script = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"script"</span>);

<span class="hljs-comment">//设置script元素的src属性</span>
<span class="hljs-keyword">var</span> src = <span class="hljs-string">"http://xxx.xx.xxx?"</span> + query;
script.src = src;

<span class="hljs-comment">//将script元素插入到文档</span>
<span class="hljs-built_in">document</span>.body.appendChild(script);
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">//定义一个JSONP组件getJSONP</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getJSONP</span>(<span class="hljs-params">url, callback</span>) </span>{
    <span class="hljs-comment">//产生一个查询字符串中的函数名,变成getJSONP的属性值，便于外部调用</span>
    <span class="hljs-keyword">var</span> cbIndex = getJSONP.cbCount;
    <span class="hljs-keyword">var</span> cbName = <span class="hljs-string">"getJSONP."</span> + getJSONP.cbCount++;

    <span class="hljs-comment">//将cbName加到url中</span>
    <span class="hljs-keyword">var</span> query = (<span class="hljs-built_in">url</span>.indexOf(<span class="hljs-string">"?"</span>) === <span class="hljs-number">-1</span>) ? (<span class="hljs-string">"?callback="</span> + cbName) : (<span class="hljs-string">"&amp;callback="</span> + cbName);
    <span class="hljs-built_in">url</span> = <span class="hljs-built_in">url</span> + query;

    <span class="hljs-comment">//生成script标签，并设置其src值</span>
    <span class="hljs-keyword">var</span> script = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"script"</span>);
    script.src = <span class="hljs-built_in">url</span>;

    <span class="hljs-comment">//定义对应cbName的回调函数，该函数里要调用callback函数</span>
    getJSON[cbIndex] = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">json</span>) </span>{
        callback(json);

        <span class="hljs-comment">//调用完成之后删除cbName对应的函数,并删除script标签</span>
        <span class="hljs-keyword">delete</span> getJSON[cbName];
        <span class="hljs-built_in">document</span>.body.removeChild(script);
    }

    <span class="hljs-comment">//将script元素插入到文档中</span>
    <span class="hljs-built_in">document</span>.body.appendChild(script);
}

<span class="hljs-comment">//初始化getJSONP的cbCount</span>
getJSONP.cbCount = <span class="hljs-number">0</span>;

<span class="hljs-comment">//可以在需要的地方使用getJSONP();</span>
......
</code></pre>
<h3 id="q2-">Q2. 深拷贝，写代码</h3>
<p>深拷贝，产生一个副本，存储了对象所有结构。浅拷贝，只是对象地址的拷贝。</p>
<pre><code class="lang-js">
//函数就直接复制其引用值了，因为函数本身不会改变，不需要副本。
function deepCopy(o) {
   <span class="hljs-built_in">var</span> result = {};
   <span class="hljs-keyword">for</span>(<span class="hljs-built_in">var</span> <span class="hljs-built_in">key</span> <span class="hljs-keyword">in</span> o) {
       <span class="hljs-keyword">if</span>(typeof o[<span class="hljs-built_in">key</span>] === <span class="hljs-string">"object"</span>) {
           <span class="hljs-keyword">if</span>(Array.isArray(o[<span class="hljs-built_in">key</span>])) {
               result[<span class="hljs-built_in">key</span>] = o[<span class="hljs-built_in">key</span>].slice(<span class="hljs-number">0</span>);
           } <span class="hljs-keyword">else</span> {
               result[<span class="hljs-built_in">key</span>] = deepCopy(o[<span class="hljs-built_in">key</span>]);
           }
       } <span class="hljs-keyword">else</span> {
           result[<span class="hljs-built_in">key</span>] = o[<span class="hljs-built_in">key</span>];
       }
   }
   <span class="hljs-built_in">return</span> result;
}
</code></pre>
<h3 id="q3-jquery-extend-">Q3. jquery的extend是浅拷贝还是深拷贝</h3>
<p>这是可选的，该函数的第一个参数为true时执行深拷贝，为false时为浅拷贝，默认为false。浅拷贝时，例如$extend(a,b)，若b中有和a相同的属性，则简单地将b的属性复制给a的对应属性（引用值复制引用，普通值复制普通值）；而在深拷贝时，普通值还是进行普通值的复制，若相同属性在b中是一个引用值，则会迭代地遍历该引用值属性的属性，将这些属性值复制给a中对应属性，表现出来的结果就是扩充a属性的效果。附jQuery源码：</p>
<pre><code class="lang-js">jQuery.extend = jQuery.fn.extend = function() {  
    var <span class="hljs-keyword">options</span>, name, src, <span class="hljs-keyword">copy</span>, copyIsArray, clone,  
        target = arguments[<span class="hljs-number">0</span>] || {},  
        i = <span class="hljs-number">1</span>,  
        length = arguments.length,  
        deep = <span class="hljs-keyword">false</span>;  

    <span class="hljs-comment">// Handle a deep copy situation  </span>
    <span class="hljs-keyword">if</span> ( typeof target === <span class="hljs-string">"boolean"</span> ) {  
        deep = target;  
        target = arguments[<span class="hljs-number">1</span>] || {};  
        <span class="hljs-comment">// skip the boolean and the target  </span>
        i = <span class="hljs-number">2</span>;  
    }  

    <span class="hljs-comment">// Handle case when target is a string or something (possible in deep copy)  </span>
    <span class="hljs-keyword">if</span> ( typeof target !== <span class="hljs-string">"object"</span> &amp;&amp; !jQuery.isFunction(target) ) {  
        target = {};  
    }  

    <span class="hljs-comment">// extend jQuery itself if only one argument is passed  </span>
    <span class="hljs-keyword">if</span> ( length === i ) {  
        target = <span class="hljs-keyword">this</span>;  
        --i;  
    }  

    <span class="hljs-keyword">for</span> ( ; i &lt; length; i++ ) {  
        <span class="hljs-comment">// Only deal with non-null/undefined values  </span>
        <span class="hljs-keyword">if</span> ( (<span class="hljs-keyword">options</span> = arguments[ i ]) != <span class="hljs-keyword">null</span> ) {  
            <span class="hljs-comment">// Extend the base object  </span>
            <span class="hljs-keyword">for</span> ( name in <span class="hljs-keyword">options</span> ) {  
                src = target[ name ];  
                <span class="hljs-keyword">copy</span> = <span class="hljs-keyword">options</span>[ name ];  

                <span class="hljs-comment">// Prevent never-ending loop  </span>
                <span class="hljs-keyword">if</span> ( target === <span class="hljs-keyword">copy</span> ) {  
                    <span class="hljs-keyword">continue</span>;  
                }  

                <span class="hljs-comment">// Recurse if we're merging plain objects or arrays  </span>
                <span class="hljs-keyword">if</span> ( deep &amp;&amp; <span class="hljs-keyword">copy</span> &amp;&amp; ( jQuery.isPlainObject(<span class="hljs-keyword">copy</span>) || (copyIsArray = jQuery.isArray(<span class="hljs-keyword">copy</span>)) ) ) {  
                    <span class="hljs-keyword">if</span> ( copyIsArray ) {  
                        copyIsArray = <span class="hljs-keyword">false</span>;  
                        clone = src &amp;&amp; jQuery.isArray(src) ? src : [];  

                    } <span class="hljs-keyword">else</span> {  
                        clone = src &amp;&amp; jQuery.isPlainObject(src) ? src : {};  
                    }  

                    <span class="hljs-comment">// Never move original objects, clone them  </span>
                    target[ name ] = jQuery.extend( deep, clone, <span class="hljs-keyword">copy</span> );  

                <span class="hljs-comment">// Don't bring in undefined values  </span>
                } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">copy</span> !== undefined ) {  
                    target[ name ] = <span class="hljs-keyword">copy</span>;  
                }  
            }  
        }  
    }  

    <span class="hljs-comment">// Return the modified object  </span>
    <span class="hljs-keyword">return</span> target;  
};
</code></pre>
<h3 id="q4-">Q4.写原型继承</h3>
<p>继承有原型链模式、借用构造函数模式、原型模式、组合继承、寄生组合式继承，其中寄生组合式继承方式最好，而原型继承如下：</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">inheritFrom</span>(<span class="hljs-params">o</span>) </span>{
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">F</span>(<span class="hljs-params"></span>) = </span>{};
    F.prototype = o;
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> F();
}
</code></pre>
<p>该方法能实现继承o的全部属性和方法，但是不能表示返回的对象的类型，因为其构造函数在外部是访问不到的，而且没有办法定义一个子类的构造函数对子类进行初始化。</p>
<p>最好的方法是使用寄生组合式继承：</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Super</span>(<span class="hljs-params">name</span>) </span>{
    <span class="hljs-keyword">this</span>.name = name;
}

Super.prototype.sayName = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">this</span>.name);
};

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Sub</span>(<span class="hljs-params">name,age</span>) </span>{
    Super.call(<span class="hljs-keyword">this</span>,name);
    <span class="hljs-keyword">this</span>.age = age;
}

Sub.prototype = <span class="hljs-built_in">Object</span>.create(Super.prototype);

Sub.prototype.sayAge = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">this</span>.age);  
};

<span class="hljs-keyword">var</span> sub1 = <span class="hljs-keyword">new</span> Sub(<span class="hljs-string">"sub1"</span>, <span class="hljs-number">20</span>);
</code></pre>
<h2 id="-">学习</h2>
<h3 id="q1-iife-">Q1. 什么是闭包，什么是IIFE?</h3>
<p>闭包就是函数以及其连接的周围作用域中的变量。</p>
<p>IIFE（立即调用函数表达式），可以形成一个块级作用域，防止某些变量被共享。</p>
<h3 id="q2-getter-setter-object-defineproperty-">Q2. getter和setter属性在定义对象自变量时的写法，和Object.defineProperty()中定义的时候的写法区别。</h3>
<h3 id="q3-jquery-">Q3. jQuery的自定义事件和原生事件在事件传播上有什么区别吗？</h3>
<h3 id="q4-">Q4. 箭头函数与普通函数的区别？</h3>
<h3 id="q5-jquery-each-">Q5. 数组的原生方法，哪些会在遍历途中停止，停止后返回什么结果？jQuery的each方法在什么时候停止，停止后返回什么结果？</h3>
<h1 id="html-web-api-">html(Web API)</h1>
<h2 id="-">面试题</h2>
<h3 id="1-svg-canvas-api-">1. SVG和canvas区别，知道哪些api，热力图用哪一种更好？</h3>
<ol>
<li>Canvas和SVG是HTML5中主要的2D图形技术，前者提供画布标签和绘制API，后者是一整套独立的矢量图形语言，成为W3C标准已经有十多年(2003.1至今)，总的来说，Canvas技术较新，从很小众发展到广泛接受，注重栅格图像处理，SVG则历史悠久，很早就成为国际标准，复杂，发展缓慢（Adobe SVG Viewer近十年没有大的更新）</li>
</ol>
<p>2.<canvas>和<svg>都是HTML5推荐使用的图形技术，Canvas基于像素，提供2D绘制函数，是一种HTML元素类型，依赖于HTML，只能通过脚本绘制图形；SVG为矢量，提供一系列图形元素（Rect, Path, Circle, Line …），还有完整的动画，事件机制，本身就能独立使用，也可以嵌入到HTML中，SVG很早就成为了国际标准，目前的稳定版本是1.1 – Scalable Vector Graphics (SVG) 1.1 (Second Edition)，两者的主要特点见下面的表格</p>
<ol>
<li>我认为热力图更适合canvas，因为需要动态地绘制大量的点，使用svg要重新渲染DOM树，性能比较缓慢。</li>
</ol>
<h3 id="2-js-">2.浏览器渲染过程。渲染引擎和JS引擎</h3>
<ol>
<li><p>浏览器渲染过程： 请求得到html文件，读取文件，原始字节解析成字符，字符解析成字符串，字符串变成标记，标记变成拥有属性和方法的DOM对象，在根据DOM对象之间的关系，构造出DOM树。在读取html文件的过程中，会遇到link标签链接到一个css文件，则此时浏览器会中止其他活动，马上请求这个文件，然后跟解析html一样，将css文件解析成CSSOM树，最后结合DOM数和CSSOM树，开始构建渲染树。这个过程中，会计算每个<strong>可见</strong>元素的大小和位置，然后浏览器根据渲染树，调用底层UI接口将图形绘制在浏览器上。</p>
</li>
<li><p>渲染过程会发生回流(reflow)和重绘(repaint),当dom结构发生改变，或者元素大小位置改变影响布局时，就会发生回流，回流会导致根据新的DOM树，或者新的CSSOM，创建新的渲染树，重新进行渲染过程，耗时较大。当元素仅仅是背景颜色改变，或者字体颜色改变，这种不影响布局的改变时，就不会创建新的渲染树，会发生重绘。对脱离文档流的元素（定位为absolute/fixed）的元素改变CSS时，不会引起回流。</p>
</li>
</ol>
<p>3.渲染引擎和JS引擎：</p>
<p>渲染引擎是一种对HTML文档进行解析并将其显示在页面上的工具。</p>
<p>JS引擎用于解析js代码并执行。js代码影响了DOM树或者CSSOM树，则渲染引擎会重新建立渲染树，重新绘制。</p>
<p>【渲染引擎】</p>
<p>firefox使用gecko引擎</p>
<p>IE使用Trident引擎</p>
<p>2015年微软推出自己新的浏览器，原名叫斯巴达，后改名edge,使用edge引擎</p>
<p>opera最早使用Presto引擎，后来弃用</p>
<p>chrome\safari\opera使用webkit引擎</p>
<p>13年chrome和opera开始使用Blink引擎</p>
<p>【JS引擎】</p>
<p>老版本IE使用Jscript引擎</p>
<p>IE9之后使用Chakra引擎</p>
<p>edge浏览器仍然使用Chakra引擎</p>
<p>firefox使用monkey系列引擎</p>
<p>safari使用的SquirrelFish系列引擎</p>
<p>Opera使用Carakan引擎</p>
<p>chrome使用V8引擎。nodeJs其实就是封装了V8引擎</p>
<h3 id="q3-websocket">Q3. websocket</h3>
<h1 id="-">网络</h1>
<h1 id="-">安全</h1>
<h2 id="-">学习</h2>
<h3 id="q1-xss-csrf">Q1. XSS与CSRF</h3>
<p>XSS（跨站脚本攻击），原理是利用script标签可以跨域加载代码的做法，引入恶意代码到客户端。危害包括，Dos，盗取cookie，钓鱼攻击等。</p>
<p>CSRF（跨站请求伪造）， 关键点有两个：跨站的请求（请求也可能来自本站）、请求是伪造的。</p>
<p>XSS的关键是脚本，CSRF的关键是请求（可以不依赖script，利用HTML 标签，比如img的src,form的action）。</p>
<h1 id="-">性能</h1>
<h1 id="-">工具使用</h1>
<h1 id="-">框架</h1>
<h2 id="-">面经</h2>
<h3 id="q1-mvc-mvp-mvvm-">Q1. 什么是MVC框架，什么是MVP，什么是MVVM框架，分别有哪些代表？</h3>
<h3 id="q2-diff-">Q2. 什么是diff算法</h3>
<p>diff算法起源是facebook的开源项目react提出的一个全新概念virtual dom，为了高效地更新dom结构，提出了diff算法，时间复杂度为O(n)。这个算法的主要思想是：</p>
<p>js先构造一个类似于真实dom的映射，对dom的操作都先在虚拟dom上模拟，不用每次更改dom都让浏览器马上进行渲染，而是在经过一系列操作之后，得到一个虚拟dom，通过diff算法对比上一次状态跟这一次状态的不同，得到一个更新方案，然后再让浏览器根据更新方案对真实dom进行操作。这样每次更新只会更新局部的不同，而不会对整个dom树进行重新的渲染。</p>
<p>【虚拟dom的概念】：
虚拟dom就是一个模拟dom树结构的抽象，其中的元素节点要比真实dom节点更小，是轻量级的dom，操作虚拟dom会更方便。</p>
<p>【diff算法】：
传统diff算法是典型的，找出任意两棵树间的最小修改问题。递归地对比每个dom节点的不同，时间复杂度为O(n^3)，</p>
<p>react的diff算法基于三个假设：</p>
<ol>
<li>不会出现跨层级的节点变化，变化只发生在同层级，因此只对比同层级的节点或组件。</li>
<li>不会有结构相似的组件，若组件不同，则他们的结构大多是不同的，遇到不同的组件，就直接删除旧组件，创建新组件。</li>
<li>同层级的兄弟元素间可以用键值区分，形成列表，当增加兄弟节点或者节点顺序发生变化时，通过在对比两个列表不同的算法，可以减少删除添加的动作。通常这种算法借助hashmap这种数据结构，可以将原本O（M*N）的复杂度降低为O（n）。</li>
</ol>
<h1 id="-">数据结构与算法</h1>
<h2 id="-">面试题</h2>
<h3 id="q1-k-">Q1. 手写链表倒数第K个查找</h3>
<h1 id="-">模块规范</h1>
<h2 id="-">学习</h2>
<h3 id="q1-amd-cmd-commonjs-">Q1. AMD/CMD/CommonJS规范</h3>
<h1 id="-">其他</h1>
<h3 id="q1-">Q1. 什么是图灵完备</h3>
<blockquote>
<p>图灵完备是对计算能力的描述。一门语言为什么要图灵完备呢？可以这么理解：一台计算机也是一个图灵机，一个图灵完备的语言意味着这个语言可以使用计算机完成任何计算机可以完成的任务，也就能够发挥计算机的所有能力。（这句话有点绕口）反之，一个图灵不完备的语言，就意味着不能发挥计算机的所有能力。这个概念也就是图灵等价。一般概念上图灵不完备指的是计算能力不如图灵机的。当然也存在计算能力可能更高的，比如说非确定图灵机。但是到底高多少，还是本质是一样的。应该没人知道，这也就是P和NP的问题。（这一段话我也不知道说的对不对，因为没印象了#_-）</p>
</blockquote>

        </article>
    </div>

    <!--footer-->
    <footer>
    
    <p>©2017-2018 &nbsp; (o^.^o) &nbsp; hh2o4</p>
    <p>Themed by hh2o4</p>
    
</footer>
    
</body>
</html>